﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UiPath.Studio.Activities.Api;
using UiPath.Studio.Activities.Api.Analyzer;
using UiPath.Studio.Activities.Api.Analyzer.Rules;
using UiPath.Studio.Analyzer.Models;


namespace TestLib3
{
    public class RuleRepository : IRegisterAnalyzerConfiguration
    {
        public void Initialize(IAnalyzerConfigurationService workflowAnalyzerConfigService)
        {
            if (!workflowAnalyzerConfigService.HasFeature("WorkflowAnalyzerV4"))
                return;

            // 变量驼峰命名检查
            var activity001Rule = new Rule<IActivityModel>("CamelCase", "ZT-VNC-001", InspectVariable001)
            {
                DefaultErrorLevel = System.Diagnostics.TraceLevel.Warning
            };

            workflowAnalyzerConfigService.AddRule<IActivityModel>(activity001Rule);

            // 变量类型命名检查
            var activity002Rule = new Rule<IActivityModel>("VariableType", "ZT-VNC-002", InspectVariable002)
            {
                DefaultErrorLevel = System.Diagnostics.TraceLevel.Warning
            };

            workflowAnalyzerConfigService.AddRule<IActivityModel>(activity002Rule);

            // 文件名检查
            var project001Rule = new Rule<IProjectModel>("Project", "ZT-FNC-001", InspectProject001)
            {
                DefaultErrorLevel = System.Diagnostics.TraceLevel.Error
            };

            workflowAnalyzerConfigService.AddRule<IProjectModel>(project001Rule);

            // 文件夹名检查
            var project002Rule = new Rule<IProjectModel>("Project", "ZT-FNC-002", InspectProject002)
            {
                DefaultErrorLevel = System.Diagnostics.TraceLevel.Error
            };

            workflowAnalyzerConfigService.AddRule<IProjectModel>(project002Rule);

            // 流程入口文件命名检查
            var project003Rule = new Rule<IProjectModel>("Project", "ZT-FNC-003", InspectProject003)
            {
                DefaultErrorLevel = System.Diagnostics.TraceLevel.Warning
            };

            workflowAnalyzerConfigService.AddRule<IProjectModel>(project003Rule);

            throw new NotImplementedException();
        }

        /// <summary>
        /// 检查字符串变量
        /// </summary>
        /// <param name="activityToInspect">activity</param>
        /// <param name="configuredRule">配置规则</param>
        /// <returns></returns>
        private InspectionResult InspectVariable001(IActivityModel activityToInspect, Rule configuredRule)
        {
            var messageList = new List<InspectionMessage>();

            string RegexStr = "^[a-z]+([A-Z][a-z]+)|([A-Z][a-z]+)$";
            bool b = false;

            foreach (var variable in activityToInspect.Variables)
            {
                b = Regex.IsMatch(variable.DisplayName, RegexStr);
                if (!b)
                {
                    messageList.Add(new InspectionMessage()
                    {
                        Message = $"变量: {variable.DisplayName} ,变量命名不符合命名规范，建议使用驼峰式命名。"
                    });
                }
            }

            if (messageList.Count > 0)
            {
                return new InspectionResult()
                {
                    HasErrors = true,
                    InspectionMessages = messageList,
                    RecommendationMessage = "变量命令使用驼峰式命名，首字母小写，命名中数据类型不强制包含，命名目的：阅读顺利，命名有意义。",
                    ErrorLevel = configuredRule.ErrorLevel
                };
            }

            return new InspectionResult { HasErrors = false };
        }

        /// <summary>
        /// 检查变量类型命名
        /// </summary>
        /// <param name="activityToInspect">activity</param>
        /// <param name="configuredRule">配置规则</param>
        /// <returns></returns>
        private InspectionResult InspectVariable002(IActivityModel activityToInspect, Rule configuredRule)
        {
            var messageList = new List<InspectionMessage>();

            Dictionary<string, string> dic = new Dictionary<string, string>();
            dic.Add("str", "System.String");
            dic.Add("int", "System.Int32");
            dic.Add("bool", "System.Boolean");
            dic.Add("obj", "System.Object");
            dic.Add("bye", "System.Byte");
            //dic.Add("sht", "System.Short");
            //dic.Add("lng", "System.Long");
            //dic.Add("flt", "System.Float");
            dic.Add("dbl", "System.Double");
            dic.Add("dec", "System.Decimal");
            dic.Add("chr", "System.Char");
            //dic.Add("enum", "System.Enumerable");
            dic.Add("arr", "System.Array");
            //dic.Add("list", "System.List");
            //dic.Add("dic", "System.Dictionary");
            //dic.Add("col", "System.Collection");
            //dic.Add("hs", "System.HashSet");
            dic.Add("dt", "System.Data.DataTable");
            dic.Add("dr", "System.Data.DataRow");
            dic.Add("ds", "System.Data.DataSet");
            dic.Add("dv", "System.Data.DataView");
            dic.Add("elm", "UiPath.Core.UiElement");
            dic.Add("sel", "UiPath.Core.Selector");
            dic.Add("wmd", "UiPath.Core.Window");
            dic.Add("dtm", "System.DateTime");
            dic.Add("gv", "UiPath.Core.GenericValue");

            string type = string.Empty;
            string r = string.Empty;
            string[] array_str;

            foreach (var variable in activityToInspect.Variables)
            {
                r = new Regex(@"
                    (?<=[A-Z])(?=[A-Z][a-z])|
                    (?<=[^A-Z])(?=[A-Z])|
                    (?<=[A-Za-z])(?=[^A-Za-z])", RegexOptions.IgnorePatternWhitespace)
                    .Replace(variable.DisplayName, "-");

                if (r != "")
                {
                    array_str = r.ToLower().Split('-');

                    type = variable.Type.Split(',')[0];

                    if (dic.ContainsKey(array_str[array_str.Length - 1]))
                    {
                        if (dic[array_str[array_str.Length - 1]] != type)
                        {
                            messageList.Add(new InspectionMessage()
                            {
                                Message = $"变量: {variable.DisplayName}，类型: {type} ,变量命名不符合命名规范，建议使用当前变量类型命名。"
                            });
                        }
                    }
                }
            }

            if (messageList.Count > 0)
            {
                return new InspectionResult()
                {
                    HasErrors = true,
                    InspectionMessages = messageList,
                    RecommendationMessage = "变量命令使用驼峰式命名，首字母小写，命名中数据类型不强制包含，命名目的：阅读顺利，命名有意义。",
                    ErrorLevel = configuredRule.ErrorLevel
                };
            }

            return new InspectionResult { HasErrors = false };
        }

        /// <summary>
        /// 检查项目文件名
        /// </summary>
        /// <param name="projectModel">project</param>
        /// <param name="configuredRule">配置规则</param>
        /// <returns></returns>
        private InspectionResult InspectProject001(IProjectModel projectModel, Rule configuredRule)
        {
            var messageList = new List<InspectionMessage>();

            string RegexStr = "[\u4e00-\u9fa5]";
            bool b = false;

            // 文件名不能使用中文
            foreach (var item in projectModel.FileNames)
            {
                b = Regex.IsMatch(item, RegexStr);
                if (b)
                {
                    messageList.Add(new InspectionMessage()
                    {
                        Message = $"文件名: {item} ，错误原因: 文件命名不允许使用中文命名。"
                    });
                }
            }

            if (messageList.Count > 0)
            {
                return new InspectionResult()
                {
                    HasErrors = true,
                    InspectionMessages = messageList,
                    RecommendationMessage = "文件命名不允许使用中文",
                    ErrorLevel = configuredRule.ErrorLevel
                };
            }

            return new InspectionResult { HasErrors = false };
        }

        /// <summary>
        /// 检查项目文件夹名
        /// </summary>
        /// <param name="projectModel">project</param>
        /// <param name="configuredRule">配置规则</param>
        /// <returns></returns>
        private InspectionResult InspectProject002(IProjectModel projectModel, Rule configuredRule)
        {
            var messageList = new List<InspectionMessage>();

            string RegexStr = "[\u4e00-\u9fa5]";
            bool c = false;

            // 文件夹名不能使用中文
            string[] s = GetDirectories(projectModel.Directory);
            foreach (var item in s)
            {
                c = Regex.IsMatch(item.Replace(projectModel.Directory, ""), RegexStr);
                if (c)
                {
                    messageList.Add(new InspectionMessage()
                    {
                        Message = $"文件夹名: { item.Replace(projectModel.Directory, "") } ，错误原因: 文件夹命名不允许使用中文命名。"
                    });
                }
            }

            if (messageList.Count > 0)
            {
                return new InspectionResult()
                {
                    HasErrors = true,
                    InspectionMessages = messageList,
                    RecommendationMessage = "文件夹命名不允许使用中文",
                    ErrorLevel = configuredRule.ErrorLevel
                };
            }

            return new InspectionResult { HasErrors = false };
        }

        /// <summary>
        /// 检查流程入口文件命名
        /// </summary>
        /// <param name="projectModel">project</param>
        /// <param name="configuredRule">配置规则</param>
        /// <returns></returns>
        private InspectionResult InspectProject003(IProjectModel projectModel, Rule configuredRule)
        {
            var messageList = new List<InspectionMessage>();

            string RegexStr = "Main";
            bool c = false;

            c = Regex.IsMatch(projectModel.EntryPointName, RegexStr);
            if (!c)
            {
                messageList.Add(new InspectionMessage()
                {
                    Message = $"流程入口文件：{ projectModel.EntryPointName } ，流程入口文件命名建议使用【Main.xaml】"
                });
            }

            if (messageList.Count > 0)
            {
                return new InspectionResult()
                {
                    HasErrors = true,
                    InspectionMessages = messageList,
                    RecommendationMessage = "文件夹命名不允许使用中文",
                    ErrorLevel = configuredRule.ErrorLevel
                };
            }

            return new InspectionResult { HasErrors = false };
        }

        /// <summary>
        /// 获取文件夹下的子文件夹
        /// </summary>
        /// <param name="dir">要搜索的文件夹</param>
        /// <returns></returns>
        private static string[] GetDirectories(string dir)
        {
            List<string> lst = new List<string>();

            foreach (string item in Directory.GetDirectories(dir))
            {
                lst.Add(item);

                lst.AddRange(GetDirectories(item));
            }

            return lst.ToArray();
        }
    }
}
